/*****************************************************************************
 *  FFTerm - Simple & Platform independent, Thread-Safe Terminal/Console     *
 *  Copyright (C) 2009  James Walmsley (james@worm.me.uk)                    *
 *                                                                           *
 *  This program is free software: you can redistribute it and/or modify     *
 *  it under the terms of the GNU General Public License as published by     *
 *  the Free Software Foundation, either version 3 of the License, or        *
 *  (at your option) any later version.                                      *
 *                                                                           *
 *  This program is distributed in the hope that it will be useful,          *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
 *  GNU General Public License for more details.                             *
 *                                                                           *
 *  You should have received a copy of the GNU General Public License        *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.    *
 *                                                                           *
 *  IMPORTANT NOTICE:                                                        *
 *  =================                                                        *
 *  Alternative Licensing is available directly from the Copyright holder,   *
 *  (James Walmsley). For more information consult LICENSING.TXT to obtain   *
 *  a Commercial license.                                                    *
 *                                                                           *
 *  See RESTRICTIONS.TXT for extra restrictions on the use of FFTerm.        *
 *                                                                           *
 *  Removing the above notice is illegal and will invalidate this license.   *
 *****************************************************************************
 *  See http://worm.me.uk/ffterm for more information.                       *
 *  Or  http://ffterm.googlecode.com/ for latest releases and the wiki.      *
 *****************************************************************************/

#include "ffterm-commands.h"
#include "ffterm.h"
#include <stdlib.h>
#include <string.h>

static int FFTerm_CmdExit(int argc, char **argv) {
	if(argc) {
		return FFT_KILL_CONSOLE;
	}
	if(argv) {

	}
	return 0;
}

const FFT_ERR_TABLE FFTerm_CmdExitInfo[] =
{
	{"Causes the active console to terminate.",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};

static int FFTerm_CmdHelp(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FFT_COMMAND *pCommand = pConsole->pCommands;
	FF_T_UINT32	i = 3;
	FF_T_SINT32	c;
	int retChar;
	/**
	 *	Removing the following notice without a commercial license is illegal.
	 **/
	fprintf(pConsole->pStdOut, "\nFFTerm v%s (%s) by James Walmsley (c)2009\n", FFT_VERSION_NUMBER, FFT_RELEASE_NAME);
	fprintf(pConsole->pStdOut, "For more information about FFTerm, see http://worm.me.uk/ffterm/\n");
	fprintf(pConsole->pStdOut, "\nAvailable Commands:\n\n");
	
	if(argc == 1) {
		while(pCommand) {
			i++;
			if((i % (FFT_CONSOLE_HEIGHT - 2)) == 0) {
				fprintf(pConsole->pStdOut, "--- Press ENTER to Continue ---\r");
				do {
					c = fgetc(pConsole->pStdIn);
					retChar = FFT_RETURN;

					if(pConsole->pSpec && pConsole->pSpec->pCustomParams) {
						retChar = (int) pConsole->pSpec->pCustomParams->ucReturnChar;
					}
				} while(c != retChar);
			}
			fprintf(pConsole->pStdOut, "%10s", pCommand->cmdName);
			if(pCommand->ErrTable) {
				fprintf(pConsole->pStdOut, " - %s", FFTerm_LookupErrMessage(pCommand->ErrTable, FFT_COMMAND_DESCRIPTION));
			}
			fprintf(pConsole->pStdOut, "\n");
			pCommand = pCommand->pNextCmd;
		}
	
		fprintf(pConsole->pStdOut, "\nFor more information about each command, type [command name] help\n\n");
		return FFT_ERR_NONE;
	}

	printf("Usage: %s\n", argv[0]);
	return FFT_ERR_NONE;
}
const FFT_ERR_TABLE FFTerm_CmdHelpInfo[] =
{
	{"List all available commands, (with description).",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};

static int FFTerm_CmdHelpList(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FFT_COMMAND *pCommand = pConsole->pCommands;

	if(argc == 1) {
		while(pCommand) {
			fprintf(pConsole->pStdOut, "%-10s", pCommand->cmdName);
			pCommand = pCommand->pNextCmd;
		}
	
		fprintf(pConsole->pStdOut, "\n\n");
		return FFT_ERR_NONE;
	}

	fprintf(pConsole->pStdOut, "Usage: %s\n", argv[0]);
	return FFT_ERR_NONE;
}
const FFT_ERR_TABLE FFTerm_CmdHelpListInfo[] =
{
	{"List all available commands, (without description).",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};

static int FFTerm_CmdTime(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FF_T_INT8 cmdLine[FFT_MAX_CMD_LINE_INPUT];
	FF_T_SINT32 i;
	FF_T_SINT32 Result;
	FF_T_UINT64 TicksPerSecond, TicksStart, TicksEnd, Ticks;

	//sprintf(cmdLine, "");
	strcpy(cmdLine, "");

	for(i = 1; i < argc; i++) {
		sprintf(cmdLine, "%s %s", cmdLine, argv[i]);
	}
	
	if(pConsole->pSpec && pConsole->pSpec->pfnGetTickRate) {
		TicksPerSecond = pConsole->pSpec->pfnGetTickRate();
	} else {
		TicksPerSecond = 1;
	}
	
	if(pConsole->pSpec && pConsole->pSpec->pfnGetTicks) {
		TicksStart = pConsole->pSpec->pfnGetTicks();
	} else {
		TicksStart = 0;
	}
		{
			Result = FFTerm_ExecCommand(pConsole, cmdLine);
		}
	if(pConsole->pSpec && pConsole->pSpec->pfnGetTicks) {
		TicksEnd = pConsole->pSpec->pfnGetTicks();
	} else {
		TicksEnd = 0;
	}

	Ticks = TicksEnd - TicksStart;

	printf("\nCommand took %llu ticks. (%0.6f seconds).\n", Ticks, (double) ((double)Ticks / (double)TicksPerSecond));

	return Result;
}
const FFT_ERR_TABLE FFTerm_CmdTimeInfo[] =
{
	{"Times the specified command.",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};


static int FFTerm_CmdLoop(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FF_T_INT8 cmdLine[FFT_MAX_CMD_LINE_INPUT];
	FF_T_SINT32 i, iterations, Result = 0;

	if(argc < 3) {
		printf("Usage: %s [iterations] [command]\n", argv[0]);
		printf("e.g.\n");
		printf("loop 3 help\n");
		return 0;
	}

	//sprintf(cmdLine, "");

	strcpy(cmdLine, "");

	for(i = 2; i < argc; i++) {
		sprintf(cmdLine, "%s %s", cmdLine, argv[i]);
	}
	
	iterations = atoi(argv[1]);//sscanf(argv[1], "%d", &i);

	if(iterations) {
		for(i = 0; i < iterations; i++) {
			Result = FFTerm_ExecCommand(pConsole, cmdLine);
		}
	} else {
		sprintf(cmdLine, "%s %s", argv[0], "usage");
		FFTerm_ExecCommand(pConsole, cmdLine);
	}

	return Result;
}
const FFT_ERR_TABLE FFTerm_CmdLoopInfo[] =
{
	{"Loops a command the specified number of times.",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};

static int FFTerm_CmdExec(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FF_T_INT8 cmdLine[FFT_MAX_CMD_LINE_INPUT];
	FF_T_SINT32 i;
	FF_T_SINT32 Result = 0;

	if(!pConsole) {
		return -1;
	}

	if(argc > 1) {
		//sprintf(cmdLine, "");

		strcpy(cmdLine, "");

		for(i = 1; i < argc; i++) {
			sprintf(cmdLine, "%s %s", cmdLine, argv[i]);
		}

		Result = system(cmdLine);
	} else {
		printf("%s [command]\n", argv[0]);
	}

	return Result;
}
const FFT_ERR_TABLE FFTerm_CmdExecInfo[] =
{
	{"Unknown or Generic Error",											-1 },
	{"Executes a native platform command (Breaks out of FFTerm).",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};


static int FFTerm_CmdPs(int argc, char **argv, FFT_CONSOLE *pConsole) {
	FF_T_SINT32 i;
	FF_T_SINT32 Result = 0;

	FFT_BGJOBS *pJobs;

	if(!pConsole) {
		return -1;
	}

	pJobs = FFTerm_GetJobs();
	if(pJobs) {
		for(i = 0; i < FFT_MAX_BG_JOBS; i++) {
			if(pJobs[i].bInUse && !pJobs[i].bExecuted) {
				printf("[%d] %s\n", pJobs[i].usPid, pJobs[i].threadParams.pArgs[0]);
			}
		}
	}

	argc = 0;	// Prevent compiler warnings.
	argv = NULL;

	return Result;
}
const FFT_ERR_TABLE FFTerm_CmdPsInfo[] =
{
	{"Unknown or Generic Error",											-1 },
	{"Displays a list of currently executing jobs.",			FFT_COMMAND_DESCRIPTION},
	{ NULL }
};

FF_T_SINT32 FFTerm_HookDefaultCommands(FFT_CONSOLE *pConsole) {
	FFTerm_AddCmd	(pConsole, "exit",	(FFT_FN_COMMAND)	FFTerm_CmdExit,		FFTerm_CmdExitInfo);
	FFTerm_AddExCmd	(pConsole, "help",	(FFT_FN_COMMAND_EX) FFTerm_CmdHelp,		FFTerm_CmdHelpInfo,		pConsole);
	FFTerm_AddExCmd	(pConsole, "?",		(FFT_FN_COMMAND_EX) FFTerm_CmdHelpList, FFTerm_CmdHelpListInfo, pConsole);
	FFTerm_AddExCmd	(pConsole, "time",	(FFT_FN_COMMAND_EX) FFTerm_CmdTime,		FFTerm_CmdTimeInfo,		pConsole);
	FFTerm_AddExCmd	(pConsole, "loop",	(FFT_FN_COMMAND_EX) FFTerm_CmdLoop,		FFTerm_CmdLoopInfo,		pConsole);
	FFTerm_AddExCmd (pConsole, "exec",	(FFT_FN_COMMAND_EX) FFTerm_CmdExec,		FFTerm_CmdExecInfo,		pConsole);
	FFTerm_AddExCmd	(pConsole, "ps",	(FFT_FN_COMMAND_EX) FFTerm_CmdPs,		FFTerm_CmdPsInfo,		pConsole);
	return FFT_ERR_NONE;
}

